<!--
 * @Date: 2022-05-07 14:25:19
 * @LastEditors: tmzdy
 * @Author: tmzdy
 * @Description: 文件
-->
<template>
	<view class="flex flex-col relative">
		
		<tm-sheet v-if="!props.hideTool" :shadow="0" :margin="[0,0]" :padding="[0,24]" _class="flex flex-row flex-row-center-center" >
			<view @click.stop="prevYear" class="px-32">
				<tm-icon :userInteractionEnabled="false" :font-size="24" name="tmicon-angle-double-left"></tm-icon>
			</view>
			<view @click.stop="prevMonth" class="px-32">
				<tm-icon :userInteractionEnabled="false" :font-size="24" name="tmicon-angle-left"></tm-icon>
			</view>
			<view class="px-12">
				<tm-text :userInteractionEnabled="false" :font-size="28" :label="_nowDate"></tm-text>
			</view>
			<view @click.stop="nextMonth" class="px-32">
				<tm-icon :userInteractionEnabled="false" :font-size="24" name="tmicon-angle-right"></tm-icon>
			</view>
			<view @click.stop="nextYear" class="px-32">
				<tm-icon :userInteractionEnabled="false" :font-size="24" name="tmicon-angle-double-right"></tm-icon>
			</view>
			<view @click="nowWeekClick" class="absolute t-0 r-16 zIndex-10" style="width: 64rpx;">
			    <tm-text :userInteractionEnabled="false" :font-size="28" label="本周"></tm-text>
			</view>
		</tm-sheet>
        
		<view class="flex flex-row flex-row-center-center py-12" :style="[{height:'74rpx'}]">
            <view  class="flex-1 flex-center" v-for="(item,index) in weekStr" :key="index" >
                <view style="width:62rpx" class="flex-center flex-col">
                    <tm-text :font-size="24" :label="item"></tm-text>
                </view>
            </view>
        </view>
        <view class="flex flex-col">
            <view  class="flex flex-row flex-row-center-center" :style="[{height:'74rpx'}]" v-for="(item,index) in _dataWeek" :key="index">
                <view :class="['opacity-5']" class="flex-1 flex-center" >
                     <view style="width:62rpx" class="flex-center flex-col">
                        <tm-text :font-size="24" :label="item"></tm-text>
                    </view>
                </view>
                <tm-sheet  no-level @click="clickWeek(item)" :height="66" :shadow="0" :round="10"  
				_class="flex-row" class="flex-6" paren-class="flex-6" 
				:text="_weekNum==item"
				:color="_weekNum==item?_color:'grey-4'" 
                
				:margin="[0,4]" :padding="[0,0]">
                    <view :userInteractionEnabled="false"   style="width:62rpx" :class="[item2.isNowIn?'':'opacity-5']" class="flex-1 flex-center" v-for="(item2,index2) in _data[index]" :key="index2" >
                        <view style="width:62rpx" class="flex-center flex-col" :style="[{opacity:item2.isVaild?'0.3':'1'}]">
                            <tm-text :font-size="28" :label="item2.date"></tm-text>
                        </view>
                    </view>
                </tm-sheet>
            </view>
        </view>
		
		<tm-button v-if="!props.hideButton" :linear="props.linear" :linear-deep="props.linearDeep" :color="props.color" @click="confirm" block  label="确认" :margin="[0,16]"></tm-button>

	</view>
</template>

<script lang="ts" setup>
/**
 * 按周选择的日历
 * @description 可以按月，按日，按周，按季度显示
 */
import {computed, ref,Ref, watch,PropType} from "vue"
import tmSheet from '../tm-sheet/tm-sheet.vue';
import tmIcon from '../tm-icon/tm-icon.vue';
import tmText from "../tm-text/tm-text.vue";
import tmButton from "../tm-button/tm-button.vue"
import * as dayjs from "../../tool/dayjs/esm/index"
import isoWeek from "../../tool/dayjs/esm/plugin/isoWeek/index"
import isSameOrBefore from "../../tool/dayjs/esm/plugin/isSameOrBefore/index"
import isBetween from "../../tool/dayjs/esm/plugin/isBetween/index"
import {weekItem} from "./interface"
import { useTmpiniaStore } from '../../tool/lib/tmpinia';
const store = useTmpiniaStore();
/**
 * 事件说明
 * v-model 绑定当前的周次时间开始和结束时间。
 * confirm 当点击确认时触发
 * click-week 点击时期上的周次时触发。
 * change 当切换年或者月的时候触发。
 */
const emits = defineEmits(["update:modelValue","confirm","click-week","change"])
const props = defineProps({
	followTheme:{
		type:Boolean,
		default:true
	},
    //默认显示的日期，自动转换为当前的周次。只会取第一个时间判断当前周次。
    defaultValue:{
        type:Array as PropType<Array<String|Number|Date>>,
        default:()=>[]
    },
    //当前的周时间段，本年度周一至周日的时间范围段。
    modelValue:{
        type:Array as PropType<Array<String|Number|Date>>,
        default:()=>[]
    },
    color:{
        type:String,
        default:'primary',
    },
    linear:{
        type:String,
        default:'',
    },
    linearDeep:{
        type:String,
        default:'light',
    },
    //指的是：有效的可选时间，小于此时间，不允许选中。
    start:{
        type:[String,Number,Date],
        default:""
    },
    //指的是：有效的可选时间，大于此时间，不允许选中。
    end:{
        type:[String,Number,Date],
        default:""
    },
    //隐藏头部操作栏
    hideTool:{
        type:Boolean,
        default:false
    },
    //隐藏底部确认按钮
    hideButton:{
        type:Boolean,
        default:false
    }
})
const _color = computed(()=>{
	if(props.followTheme&&store.tmStore.color) return store.tmStore.color;
	return props.color
})
const DayJs = dayjs.default;
DayJs.extend(isoWeek)
DayJs.extend(isSameOrBefore)
DayJs.extend(isBetween)
//当前的时间
const _value = ref( DayJs(props.defaultValue[0]).isValid()?DayJs(props.defaultValue[0]):DayJs())
//当前的周次。
const _weekNum = ref(getNowWeek(_value.value))
const weekStr = ['周次','一','二','三','四','五','六','日']
const _data:Ref<Array<Array<weekItem>>> = ref([]);
const _dataWeek:Ref<Array<number>> = ref([]);//本月的周次。
const _start_date = computed(()=>{
    let isv = DayJs(props.start).isValid()
    return isv?DayJs(props.start):DayJs('1980-1-1')
})
const _end_date = computed(()=>{
    let isv = DayJs(props.end).isValid()
    return isv?DayJs(props.end):DayJs('2450-1-1')
})

//当前的年月日期。
const _nowDate = computed(()=>{
    return _value.value.format("YYYY-MM")
})
_data.value = getWeekOfMonthArray();

watch(()=>props.modelValue,()=>{
    if(!Array.isArray(props.modelValue)) return;
    let date_str = props.modelValue[0]??'';
    _value.value = DayJs(date_str).isValid()?DayJs(date_str):DayJs();
    _weekNum.value = getNowWeek(_value.value)
	_data.value = getWeekOfMonthArray();
},{deep:true})
//获取当前周次。根据当前日期。
function getNowWeek(str:string|dayjs.Dayjs|number|Date='') {
    if(DayJs(str).isValid()){
        return DayJs(str).isoWeek()
    }else{
        return DayJs().isoWeek()
    }
}
function nowWeekClick(){
	_value.value = DayJs();
    _data.value = getWeekOfMonthArray();
    let wk = getNowWeek(_value.value);
    if(!canSelected(wk)){
        uni.showToast({title:"无法选中",icon:'none'})
        return;
    }
	_weekNum.value = wk
	
    updateTimes()
}
function clickWeek(wk:number){
    if(!canSelected(wk)){
        uni.showToast({title:"无法选中",icon:'none'})
        return;
    }
    _weekNum.value = wk;
    updateTimes()
}
function canSelected(num:number){
    // 能否选中周次。
    let index  = _dataWeek.value.findIndex(el=>el==num);
    let item = _data.value[index];
    let ar = item.filter(el=>!el.isVaild)
    return ar.length==7
}
function nextYear(){
    _value.value = _value.value.add(1,'year');
    _data.value = getWeekOfMonthArray();
    emits("change",_value.value.format("YYYY/MM/DD"))
}
function nextMonth(){
    _value.value = _value.value.add(1,'month');
    _data.value = getWeekOfMonthArray();
    emits("change",_value.value.format("YYYY/MM/DD"))
}
function prevMonth(){
    _value.value = _value.value.subtract(1,'month');
    _data.value = getWeekOfMonthArray();
    emits("change",_value.value.format("YYYY/MM/DD"))
}
function prevYear(){
     _value.value = _value.value.subtract(1,'year');
    _data.value = getWeekOfMonthArray();
    emits("change",_value.value.format("YYYY/MM/DD"))
}


//设置当前选中的日期范围，参数为周次中的某一个日期即可，会自动转换成以该日期为周的范围段。
function setDefault(data:Array<String|Number|Date>=[]){
    let date_str = data[0];
    _value.value = DayJs(date_str).isValid()?DayJs(date_str):DayJs();
    _weekNum.value = getNowWeek(_value.value)
	_data.value = getWeekOfMonthArray();
}

//获取本月按周分组的时间段。
function getWeekOfMonthArray(){
    let nowMonth:dayjs.Dayjs = DayJs(_value.value)
    let startStatickDay = nowMonth.startOf('month').format('YYYY/MM/DD');
    let endStatickDay = nowMonth.endOf('month').format('YYYY/MM/DD');
    let startd = DayJs(startStatickDay)
    
    let arOfmonth:Array<number> = [];//本月的周次。
    let ar:Array<weekItem> = [];
    while(startd.isSameOrBefore(endStatickDay)){
        ar.push({
            dateStr:startd.format("YYYY/MM/DD"),
            date:startd.date()<10?'0'+startd.date():startd.date(),
            week:startd.isoWeek(),
            day:startd.isoWeekday(),
            isNowIn:isInNowMonth(nowMonth,startd),
            isVaild:!startd.isBetween(_start_date.value,_end_date.value,'day','[]')
        })
        arOfmonth.push(startd.isoWeek())
        startd = startd.add(1,'day')
    }
    arOfmonth = [...new Set(arOfmonth)]
    _dataWeek.value = arOfmonth;
    let dArray:Array<Array<weekItem>> = [];
    let index=0;
    dArray.push([])
    ar.forEach(el=>{
        if(el.week == arOfmonth[index]){
            dArray[index].push(el)
        }else{
            index +=1;
            dArray.push([])
            dArray[index].push(el)
        }
    })
    //补齐前尾的7天时间。
    if(dArray[0].length!==7){
        let item = dArray[0][dArray[0].length-1];
        let start_of = DayJs(item.dateStr).isoWeek(item.week).subtract(6,'day')
        let end_of = DayJs(item.dateStr).isoWeek(item.week)
        let pr = [];
        let startd = DayJs(start_of)
        while(startd.isSameOrBefore(end_of)){
            pr.push({
                dateStr:startd.format("YYYY/MM/DD"),
                date:startd.date()<10?'0'+startd.date():startd.date(),
                week:startd.isoWeek(),
                day:startd.isoWeekday(),
                isNowIn:isInNowMonth(nowMonth,startd),
                isVaild:!startd.isBetween(_start_date.value,_end_date.value,'day','[]')
            })
            startd = startd.add(1,'day')
        }
        dArray[0] = pr;
    }
    if(dArray[dArray.length-1].length!==7){
        let item = dArray[dArray.length-1][0];
        
        let start_of = DayJs(item.dateStr).isoWeek(item.week)
        let end_of = DayJs(item.dateStr).isoWeek(item.week).add(6,'day')
        let pr = [];
        let startd = DayJs(start_of)
        while(startd.isSameOrBefore(end_of)){
            pr.push({
                dateStr:startd.format("YYYY/MM/DD"),
                date:startd.date()<10?'0'+startd.date():startd.date(),
                week:startd.isoWeek(),
                day:startd.isoWeekday(),
                isNowIn:isInNowMonth(nowMonth,startd),
                isVaild:!startd.isBetween(_start_date.value,_end_date.value,'day','[]')
            })
            startd = startd.add(1,'day')
        }
        dArray[dArray.length-1] = pr;
    }
    return dArray;
}
// 检测now日期是否在某个日期的月份中.
function isInNowMonth(date:string|dayjs.Dayjs|number='',now:string|dayjs.Dayjs|number=''){
    let startStatickDay = DayJs(date).startOf('month').format('YYYY/MM/DD');
    let endStatickDay =  DayJs(date).endOf('month').format('YYYY/MM/DD');
    return DayJs(now).isBetween(startStatickDay,endStatickDay, 'day', '[]')
}

//update
function updateTimes(){
    let index  = _dataWeek.value.findIndex(el=>el==_weekNum.value);
    let item = _data.value[index];
    let start = item[0].dateStr
    let end = item[item.length-1].dateStr
	emits("click-week",[start,end])
}
function confirm(){
    let index  = _dataWeek.value.findIndex(el=>el==_weekNum.value);
    let item = _data.value[index];
    let start = item[0].dateStr
    let end = item[item.length-1].dateStr
    emits("update:modelValue",[start,end])
    emits("confirm",[start,end])
    
}
defineExpose({
    setDefault:setDefault,
    nextYear:nextYear,
    nextMonth:nextMonth,
    prevYear:prevYear,
    prevMonth:prevMonth,
})

</script>

<style>

</style>
